<template>
  <div class="wrap">
    <ul id="box">
      <li
        v-for="(item,idx) of liElemMaxNum"
        :key="idx"
        :style="styleArray[idx]"
        @mouseover="handleOver"
        @mouseout="handleOut"
        @click="calcStyle(contentArray[idx])"
      >{{contentArray[idx]}}</li>
    </ul>
    <div class="mask">
      <div class="bg-mask"></div>
    </div>
  </div>
</template>

<script>
export default {
  data() {
    return {
      el: null,
      currentType: "Grid", //展示类型
      liElemMaxNum: 300, //矩阵数量

      liElemOffsetX: 350, // li 元素水平方向的最大间隔距离
      liElemOffsetY: 350, // li 元素垂直方向的最大间隔距离
      liElemOffsetZ: 350, // li 元素纵深方向的最大间隔距离
      liElemDepDefault: -1000, // li 元素默认景深
      depDefault: -1000, // 避免覆盖默认景深值
      liElemDegX: 0, // x偏移度数
      liElemDegY: 0, // y偏移度数
      liElemDepZ: -1600, // z偏移度数
      liElemRowMaxNum: 5, // li 元素 水平铺放的最大个数
      liElemColMaxNum: 5, // li 元素 垂直铺放的最大个数
      aScreenNum: null,

      liElemDepMaxDist: null,
      liElemFristSiteX: null, // 计算第一个li 元素的坐标点 x
      liElemFristSiteY: null, // 计算第一个li 元素的坐标点 y
      liElemFristSiteZ: null, // 计算第一个li 元素的坐标点 z
      oldCoordX: null, // 鼠标X、Y坐标值
      oldCoordY: null, // 鼠标X、Y坐标值
      nowCoordX: null, // 鼠标X、Y坐标值
      nowCoordY: null, // 鼠标X、Y坐标值
      minusX: null, // 鼠标X、Y差值
      minusY: null, // 鼠标X、Y差值
      type: [
        "Grid",
        "Helix",
        "Chaotic",
        "Sphere",
        "Three",
        "Geome",
        "Curve",
        "Random"
      ],
      styleArray: [],
      contentArray: [],
      timer: null
    };
  },
  created() {
    // 一层多少个方块
    this.aScreenNum = this.liElemRowMaxNum * this.liElemColMaxNum;
    // li 元素纵深方向的最在间隔距离
    this.liElemDepMaxDist = parseInt(this.liElemMaxNum / this.aScreenNum);
    // 计算第一个li 元素的坐标点 x y z
    this.liElemFristSiteX =
      parseInt("-" + this.liElemRowMaxNum / 2) * this.liElemOffsetX;
    this.liElemFristSiteY =
      parseInt("-" + this.liElemColMaxNum / 2) * this.liElemOffsetY;
    this.liElemFristSiteZ =
      parseInt("-" + this.liElemDepMaxDist / 2) * this.liElemOffsetZ;
  },
  mounted() {
    window.addEventListener("mousewheel", this.handleScroll, false);
    window.addEventListener("mousedown", this.handleMousedown, false);
    window.addEventListener("mouseup", this.handleMouseup, false);
    this.el = document.getElementById("box");
    this.launchFullscreen();
    this.calcStyle(this.currentType);
  },
  methods: {
    // 判断各种浏览器，找到正确的方法
    launchFullscreen() {
      let element = document;
      if (element.requestFullscreen) {
        element.requestFullscreen();
      } else if (element.mozRequestFullScreen) {
        element.mozRequestFullScreen();
      } else if (element.webkitRequestFullscreen) {
        element.webkitRequestFullscreen();
      } else if (element.msRequestFullscreen) {
        element.msRequestFullscreen();
      }
    },
    // 鼠标点击
    handleMousedown(event) {
      window.addEventListener("mousemove", this.handleMousemove, false);
      // 上一个点的X、Y坐标
      this.oldCoordX = event.clientX;
      this.oldCoordY = event.clientY;
    },
    // 鼠标释放
    handleMouseup(event) {
      window.removeEventListener("mousemove", this.handleMousemove, false);
      // 若上一个定时器存在，则将其删除
      this.timer && clearInterval(this.timer);

      // 鼠标弹起后有缓动效果
      this.timer = setInterval(_ => {
        // 缓动差值
        this.minusX *= 0.95;
        this.minusY *= 0.95;

        // 计算X、Y轴的移动度数
        this.liElemDegX -= this.minusY * 0.1;
        this.liElemDegY += this.minusX * 0.1;

        // 当差值超出指定范围时，则清除定时器
        Math.abs(this.minusX) < 0.05 &&
          Math.abs(this.minusY) < 0.05 &&
          clearInterval(this.timer);

        this.el.style.transform = `translateZ(${this.liElemDepZ}px) rotateX(${this.liElemDegX}deg) rotateY(${this.liElemDegY}deg)`;
      }, 12);
    },
    // 鼠标移动
    handleMousemove(event) {
      // 若上一个定时器存在，则将其删除
      this.timer && clearInterval(this.timer);
      // 当前点的X、Y坐标
      this.nowCoordX = event.clientX;
      this.nowCoordY = event.clientY;
      // 计算机X、Y差值
      this.minusX = this.nowCoordX - this.oldCoordX;
      this.minusY = this.nowCoordY - this.oldCoordY;
      // 更新上一个点的X、Y坐标值
      this.oldCoordX = this.nowCoordX;
      this.oldCoordY = this.nowCoordY;
      // 计算X、Y轴的移动度数
      this.liElemDegX -= this.minusY * 0.1;
      this.liElemDegY += this.minusX * 0.1;
      this.el.style.transform = `translateZ(${this.liElemDepZ}px) rotateX(${this.liElemDegX}deg) rotateY(${this.liElemDegY}deg)`;
    },
    // 滚轮滚动
    handleScroll(e) {
      let el = document.getElementById("box");
      // 若上一个定时器存在，则将其删除
      this.timer && clearInterval(this.timer);
      let step = e.deltaY > 0 ? -1 : 1; //该语句可以用来判断滚轮是向上滑动还是向下
      // 计算滚轮滚动时Z 轴景深的步长
      this.liElemDepZ = this.depDefault += step * 90;
      el.style.transform = `translateZ(${this.liElemDepZ}px) rotateX(${this.liElemDegX}deg) rotateY(${this.liElemDegY}deg)`;

      // 设置缓动效果
      this.timer = setInterval(_ => {
        // 缓动步长
        step *= 0.6;
        this.liElemDepZ += step * 80;

        Math.abs(step) < 0.000005 && clearInterval(this.timer);
        el.style.transform = `translateZ(${this.liElemDepZ}px) rotateX(${this.liElemDegX}deg) rotateY(${this.liElemDegY}deg)`;
      }, 12);
    },
    // 计算每个元素的位置
    calcStyle(type) {
      console.log(type);
      let liArr = [];
      for (let i = 0; i < this.liElemMaxNum; i++) {
        let r = this.randomFrom(100, 255);
        let g = this.randomFrom(100, 255);
        let b = this.randomFrom(100, 255);
        if (type == "Grid") {
          // 计算li 元素 水平、垂直、纵深方向的偏移位
          let offsetStepX =
            ((i % this.aScreenNum) % this.liElemRowMaxNum) * this.liElemOffsetX;
          let offsetStepY =
            parseInt((i % this.aScreenNum) / this.liElemColMaxNum) *
            this.liElemOffsetY;
          let offsetStepZ = parseInt(i / this.aScreenNum) * this.liElemOffsetZ;

          // 计算当前li 元素的坐标值
          this.liElemCoordX = this.liElemFristSiteX + offsetStepX;
          this.liElemCoordY = this.liElemFristSiteY + offsetStepY;
          this.liElemCoordZ = this.liElemFristSiteZ + offsetStepZ;
          liArr.push({
            transform: `translate3d(${this.liElemCoordX}px,${this.liElemCoordY}px,${this.liElemCoordZ}px)`,
            transition: "4s ease-in-out",
            color: `rgb(${r},${g},${b})`
          });
          this.contentArray.push(
            this.type[this.randomFrom(0, this.type.length - 1)]
          );
        } else if (type == "Helix") {
          this.liElemDegY = 10 * i;
          this.liElemDepY = -10 * parseInt(this.liElemMaxNum / 2) + 10 * i;
          liArr.push({
            transition: "4s ease-in-out",
            color: `rgb(${r},${g},${b})`,
            transform: `rotateY(${this.liElemDegY}deg) translateY(${
              this.liElemDepY
            }px) translateZ(${Math.abs(this.liElemDepDefault)}px)`
          });
        } else if (type == "Sphere") {
          this.liElemDegY = 3 * i;
          this.liElemDegX = 30 * i;
          liArr.push({
            transition: "4s ease-in-out",
            color: `rgb(${r},${g},${b})`,
            transform: `rotateY(${this.liElemDegY}deg) rotateX(${
              this.liElemDegX
            }deg) translateZ(${Math.abs(this.liElemDepDefault)}px)`
          });
        } else if (type == "Three") {
          this.liElemDegY = 3 * i;
          this.liElemDegX = 60 * i;
          liArr.push({
            transition: "4s ease-in-out",
            color: `rgb(${r},${g},${b})`,
            transform: `rotateY(${this.liElemDegY}deg) rotateX(${
              this.liElemDegX
            }deg) translateZ(${Math.abs(this.liElemDepDefault)}px)`
          });
        } else if (type == "Geome") {
          //"Grid","Helix", "Chaotic", "Sphere", "Three", "Geome", "Curve", "Random";
          this.liElemDegY = 10 * i;
          this.liElemDegX = 3 * i;
          liArr.push({
            transition: "4s ease-in-out",
            color: `rgb(${r},${g},${b})`,
            transform: `rotateY(${this.liElemDegY}deg) rotateX(${
              this.liElemDegX
            }deg) translateZ(${Math.abs(this.liElemDepDefault)}px)`
          });
        } else if (type == "Curve") {
          //"Grid","Helix", "Chaotic", "Sphere", "Three", "Geome", "Curve", "Random";
          this.liElemDegY = 2 * i;
          this.liElemDegX = 2 * i;
          liArr.push({
            transition: "4s ease-in-out",
            color: `rgb(${r},${g},${b})`,
            transform: `rotateY(${this.liElemDegY}deg) rotateX(${
              this.liElemDegX
            }deg) translateZ(${Math.abs(this.liElemDepDefault)}px)`
          });
        } else {
          this.liElemCoordX = (Math.random() - 0.5) * 3000;
          this.liElemCoordY = (Math.random() - 0.5) * 3000;
          this.liElemCoordZ = (Math.random() - 0.5) * 3000;
          liArr.push({
            transition: "4s ease-in-out",
            color: `rgb(${r},${g},${b})`,
            transform: `translate3d(${this.liElemCoordX}px,${this.liElemCoordY}px,${this.liElemCoordZ}px)`
          });
        }
      }
      this.styleArray = liArr;
    },
    // 鼠标移入
    handleOver(e) {
      e.preventDefault();
      let self = e.target.tagName.toLowerCase();
      if (self == "li") {
        e.target.style.border = "1px solid rgba(125,255,255,0.75)";
        e.target.style.boxShadow = "0 0 15px rgba(0,255,255,1)";
        e.target.style.transition = "0.3s";
      }
    },
    // 鼠标移出
    handleOut(e) {
      e.preventDefault();
      let self = e.target.tagName.toLowerCase();
      if (self == "li") {
        e.target.style.border = "1px solid rgba(125,255,255,0.25)";
        e.target.style.boxShadow = "0 0 15px rgba(0,255,255,0.5)";
        e.target.style.transition = "0.3s";
      }
    },
    // 指定一个区间，获取一个随机数
    randomFrom: (lowerValue, upperValue) => {
      return Math.floor(
        Math.random() * (upperValue - lowerValue + 1) + lowerValue
      );
    }
  }
};
</script>

<style lang="scss" scoped>
* {
  margin: 0;
  padding: 0;
  user-select: none;
}
html,
body {
  height: 100%;
}

li {
  list-style-type: none;
}

.wrap {
  height: 100%;
  overflow: hidden;
  perspective: 800px;
}

#box {
  top: 50%;
  left: 50%;
  width: 0;
  height: 0;
  position: relative;
  transform-style: preserve-3d;
  transform: translateZ(-1600px);
  z-index: 1;
}
#box li {
  top: -80px;
  left: -60px;
  width: 120px;
  height: 160px;
  position: absolute;
  text-align: center;
  line-height: 160px;
  background-color: rgba(5, 100, 80, 0.2);
  border: 1px solid rgba(125, 255, 255, 0.25);
  box-shadow: 0 0 15px rgba(0, 255, 255, 0.5);
  cursor: pointer;
}
#box li span {
  font-size: 28px;
  font-weight: blod;
  text-shadow: 2px 2px 5px black;
  color: #efebef;
}

.mask {
  width: 100%;
  height: 100%;
  background: url("~@/assets/images/space.jpg") no-repeat center;
  background-size: cover;
  filter: blur(5px);
}
.mask > .bg-mask {
  width: 100%;
  height: 100%;
  background: #000;
  opacity: 0.25;
}
</style>